/*
Copyright 2009 - 2013 Peter Krajnc, SCREENWORKER

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/
package org.compactmvc.core
{
	import org.compactmvc.interfaces.IModel;
	import org.compactmvc.patterns.Controller;
	import org.compactmvc.vo.NoteVO;
	
	/**
	 * MVC Core
	 * @author Peter Krajnc
	 * 
	 */	
	public class CompactMVC
	{
		public static const VERSION: String 			= "2.0.1";
		public static const AUTHOR:String 				= "Peter Krajnc, SCREENWORKER";
		public static const SOURCE:String 				= "http://compactmvc.googlecode.com/svn/trunk/";
		public static const EXAMPLE_FLEX:String 		= "http://compactmvc-example-flex.googlecode.com/svn/trunk/";
		public static const EXAMPLE_FLASH:String 		= "http://compactmvc-example-flash.googlecode.com/svn/trunk/";
		public static const EXAMPLE_AIR:String 			= "http://compactmvc-example-air.googlecode.com/svn/trunk/";
		
		//Log Level
		public static const LOGLEVEL_ALL:String 		= 'all';
		public static const LOGLEVEL_DEBUG:String 		= 'debug';
		public static const LOGLEVEL_NONE:String 		= 'none';
		
		/*	DI Annotations:
			
		[Inject] initialize and removes the instance via DI (Dependency Injection)

		//todo
		Control of the life cycle ):
	    [Execute] executes the annotated method of a handler class, as soon as the handler is called
	    [PostConstruct] executes the annotated method after the instantiation is complete via DI is (typically use methods to create the UI)
	    [PreDestroy] executes the annotated method before the object is deleted
		*/
		public static const ANNOTATION_INJECT:String			= 'Inject';
		public static const ANNOTATION_EXECUTE:String			= 'Execute';
		public static const ANNOTATION_POST_CONSTRUCT:String	= 'PostConstruct';
		public static const ANNOTATION_PRE_DESTROY:String		= 'PreDestroy';
		
		//Singleton Instance
		private static var instance:CompactMVC;
		private var _core:Core;

		/**
		* Static accessor method.
		* @return A unique instance of this class.
		*/
		public static function getInstance():CompactMVC 
		{	
			if(!instance)
			{
				instance = new CompactMVC( new SingletonEnforcer() );
			}
			return instance;
			
		}
		
		/**
		 * constructor 
		 * @param enforcer Singleton enforcer
		 * 
		 */		
		public function CompactMVC(enforcer:SingletonEnforcer) 
		{
			if (!enforcer)
			{
				throw new Error('CompactMVC must be instantiated through CompactMVC.getInstance()');
			}
			_core = new Core();	
		}
		
      	/**
      	 * registers the view instance
      	 * @param controllerName
      	 * @param viewName
      	 * @param viewInstance
      	 * 
      	 */		
      	public function registerView(controllerName:String, viewName:String, viewInstance:Object):void
      	{    		
      		core.registerView(controllerName, viewName, viewInstance);
      	}
      	
      	/**
      	 * remove the registered view instance
      	 * @param controllerName
      	 * @param viewName
      	 * @param viewInstance
      	 * 
      	 */		
      	public function removeView(controllerName:String, viewName:String):void
      	{    		
      		core.removeView(controllerName, viewName);
      	}
		
		/**
		 * retrieves a registered Model 
		 * @param controller
		 * @param modelName
		 * @return iModel
		 * 
		 */  	
		public function retrieveView(controllerName:String, viewName:String):Object
		{
			return core.retrieveView(controllerName, viewName);
		}
		
		/**
		 * retrieves a registered Model 
		 * @param controller
		 * @param modelName
		 * @return iModel
		 * 
		 */  	
		public function retrieveModel(controllerName:String, modelName:String):IModel
		{
			return core.retrieveModel(core.retrieveController(controllerName), modelName);
		}
		
		/**
		 * checks whether a view is present
		 * @param controllerName
		 * @param viewName
		 * @return 
		 * 
		 */		
		public function isViewRegistered(controllerName:String, viewName:String):Boolean
		{    		
			return core.isViewRegistered(controllerName, viewName);
		}
      	
		/**
		 * notifies one controller by name 
		 * @param controllerName
		 * @param notificationType
		 * @param data
		 * 
		 */      	
		public function sendNotificationTo(controllerName:String, notificationType:String, data:Object=null, delay:Number=0):void 
		{	
			core.retrieveController(controllerName).sendNotification( new NoteVO(notificationType, data), delay );
		}
		
		/**
		 * 
		 * @param notificationType
		 * @param data
		 * @param delay
		 * 
		 */		
		public function sendJunctionNotification(notificationType:String, data:Object=null, delay:Number=0):void
		{
			var controllers:Array = core.retrieveRegisteredControllers();
			for each(var item:Controller in controllers)
			{
				item.sendNotification( new NoteVO(notificationType, data), delay );
				//trace("sendJunctionNotification:" + item.getName() + " type:" + notificationType);
			}
		}
		
		/**
		 * returns the core Instance 
		 * @return 
		 * 
		 */	
		public function get core():Core
		{
			return _core;
		}
		
	}
}
class SingletonEnforcer {}
